import copy
import datetime

def savepos(pos, name="pos"):
    from jili.core import save
    import os
    #baseurl=os.path.realpath(__file__)
    base_url=os.path.abspath(os.path.dirname(os.path.realpath(__file__))+ os.path.sep + "../../deps/qlyserver/data"+os.path.sep+name)
    save(pos,base_url)
class DataSet:
    def __init__(self,size=None,timekey=None,data=None):
        self.dataset=[]
        self.curtimekey=None
        if size:
            self.size=size+1
        else:
            self.size = size
        if data:
            t = {}
            t["timekey"]=timekey
            if isinstance(data,dict):
                t.update(data)
            else:
                t["data"]=data
            self.curtimekey = timekey
            self.dataset.append(t)
    def updatedata(self,timekey,data):
        if not self.curtimekey:
            t = {}
            t["timekey"] = timekey
            if isinstance(data,dict):
                t.update(data)
            else:
                t["data"]=data
            self.dataset.append(t)
        elif self.curtimekey==timekey:
            t =self.dataset[-1]
            t["timekey"] = timekey
            if isinstance(data,dict):
                t.update(data)
            else:
                t["data"]=data
        else:
            t = {}
            t["timekey"] = timekey
            if isinstance(data,dict):
                t.update(data)
            else:
                t["data"]=data
            self.dataset.append(t)
        self.curtimekey = timekey
        if self.size:
            if len(self.dataset)>=self.size:
                self.dataset.pop(0)
    def getpredata(self,timekey):
        if self.curtimekey:
            if self.curtimekey==timekey:
                if len(self.dataset)>1:
                    return self.dataset[-2]
                else:
                    return None
            else:
                return self.dataset[-1]
        else:
            return None
class BSOrders:
    def __init__(self):
        self.bsorders=[]
    def add(self,timekey,bs,price,**argv):
        t={}
        t["timekey"]=timekey
        t["bs"]=bs
        t["price"]=price
        t.update(argv)
        self.bsorders.append(t)
    def reset(self):
        self.bsorders=[]
    def __iter__(self):
        return iter(self.bsorders)
class pos_reserch_fixqty:
    def  __init__(self,reserver=False):
        """
        单品种交易研究；支持净值曲线
        支持多层次开仓，多次平仓；先开先平
        支持多空同时持仓
        buy 买持仓单
        sell 买持仓单
        orders 完成一笔买卖订单
        stat：持仓状态
        逐笔结算方式
        qty=1
        """
        self.buyorders=[]
        self.sellorders=[]
        self.orders=[]
        self.bstoday=BSOrders()
        self.stat="null"#
        self.reserver=reserver
        self.preprice=DataSet(size=2)
        self.returnsobj=DataSet()
        self.returns=self.returnsobj.dataset
        self.returns_df=None
        self.rr=None
        self.summarydata={}
        self.ssconfig={}
    def setssconfig(self,ssconfig):
        self.ssconfig=ssconfig
    def reserverbs(self):
        orderbs=[]
        for i in self.orders:
            t = {}
            """
            for k,v in i.items():
                t[k]=v
            """
            t["timekey"]=t["timekey"]
            t["buytime"]=i["selltime"]
            t["buyprice"]=i["sellprice"]
            t["selltime"] = i["buytime"]
            t["sellprice"] = i["buyprice"]
            t["pl"]=-i["pl"]
        orderbs.append(t)
        import pandas as pd
        rst = {}
        if orderbs:
            o = pd.DataFrame(self.orders)
            rst["总收益点数_逐笔"] = o["pl"].sum()
            rst["交易来回数_逐笔"] = len(o)
            rst["均收益_逐笔"] = rst["总收益点数_逐笔"] / rst["交易来回数_逐笔"]
            rst["0笔数_逐笔"] = len(o[o["pl"] == 0])
            rst["赚钱笔数_逐笔"] = len(o[o["pl"] > 0])
            rst["亏钱笔数_逐笔"] = len(o[o["pl"] < 0])
            rst["胜率_逐笔"] = rst["赚钱笔数_逐笔"] / rst["亏钱笔数_逐笔"]
            rst["盈亏比_逐笔"] = (o[o["pl"] > 0]["pl"].sum()) / abs(o[o["pl"] < 0]["pl"].sum())
        return rst
    def buy(self, price, timekey):
        if self.reserver:
            self.__sell(price, timekey)
        else:
            self.__buy(price, timekey)
    def sell(self, price, timekey):
        if not self.reserver:
            self.__sell(price, timekey)
        else:
            self.__buy(price, timekey)
    def sellopen(self, price, timekey):
        if not self.reserver:
            self.__sellopen(price, timekey)
        else:
            self.__buyopen(price, timekey)
    def buyopen(self, price, timekey):
        if self.reserver:
            self.__sellopen(price, timekey)
        else:
            self.__buyopen(price, timekey)
    def buyclose(self, price, timekey):
        if self.reserver:
            self.__sellclose(price, timekey)
        else:
            self.__buyclose(price, timekey)
    def sellclose(self, price, timekey):
        if not self.reserver:
            self.__sellclose(price, timekey)
        else:
            self.__buyclose(price, timekey)
    def closelong(self, price, timekey):
        if self.reserver:
            self.__closeshort(price, timekey)
        else:
            self.__closelong(price, timekey)
    def closeshort(self, price, timekey):
        if not self.reserver:
            self.__closeshort(price, timekey)
        else:
            self.__closelong(price, timekey)
    def __buy(self,price,timekey):
        if self.sellorders:
            for i in self.sellorders:
                i["buyprice"]=price
                i["buytimekey"]=timekey
                i["pl"]=(i["sellprice"]-i["buyprice"]-1)
                self.orders.append(i)
                self.bstoday.add(timekey,"buy",price,openclose="close")
        pos={"timekey":timekey,"buyprice":price,"buytimekey":timekey,"qty":1}
        self.buyorders.append(pos)
        self.bstoday.add(timekey,"buy",price+1,openclose="open")
        self.stat="long"
    def __sell(self,price,timekey):
        if self.buyorders:
            for i in self.buyorders:
                i["sellprice"]=price
                i["selltimekey"]=timekey
                i["pl"] = (i["sellprice"] - i["buyprice"] - 1)
                self.orders.append(i)
                self.bstoday.add(timekey,"sell",price,openclose="close")
        pos={"timekey":timekey,"sellprice":price,"selltimekey":timekey,"qty":1}
        self.sellorders.append(pos)
        self.bstoday.add(timekey,"sell",price-1,openclose="open")
        self.stat="short"
    def __buyopen(self,price,timekey):
        pos = {"timekey":timekey,"buyprice": price, "buytimekey": timekey, "qty": 1}
        self.buyorders.append(pos)
        self.bstoday.add(timekey,"buy",price+1,openclose="open")
        if self.sellorders:
            self.stat="all"
        else:
            self.stat = "long"
    def __sellopen(self,price,timekey):
        pos = {"timekey":timekey,"sellprice": price, "selltimekey": timekey, "qty": 1}
        self.sellorders.append(pos)
        self.bstoday.add(timekey,"sell",price-1,openclose="open")
        if self.buyorders:
            self.stat="all"
        else:
            self.stat="short"
    def __buyclose(self,price,timekey):
        self.__closeshort(price,timekey)
    def __sellclose(self,price,timekey):
        self.__closelong(price,timekey)
    def __closelong(self,price,timekey):
        if self.buyorders:
            for i in self.buyorders:
                i["sellprice"]=price
                i["selltimekey"]=timekey
                i["pl"] = (i["sellprice"] - i["buyprice"] - 1) 
                self.orders.append(i)
                self.bstoday.add(timekey,"sell",price,openclose="close")
            self.buyorders=[]
        if self.sellorders:
            self.stat="short"
        else:
            self.stat="null"
    def __closeshort(self,price,timekey):
        if self.sellorders:
            for i in self.sellorders:
                i["buyprice"]=price
                i["buytimekey"]=timekey
                i["pl"]=(i["sellprice"]-i["buyprice"]-1)
                self.orders.append(i)
                self.bstoday.add(timekey,"buy",price,openclose="close")
            self.sellorders=[]
        if self.buyorders:
            self.stat="long"
        else:
            self.stat="null"
    def checkstat(self):
        if self.sellorders:
            if self.buyorders:
                self.stat = "all"
            else:
                self.stat = "short"
        else:
            if self.buyorders:
                self.stat = "long"
            else:
                self.stat = "null"
    def netonafterday(self,t):
        tk=t["timekey"]
        timekey=datetime.datetime(year=tk.year,month=tk.month,day=tk.day)
        predata=self.preprice.getpredata(timekey)
        preprice=None
        preBpos=0
        preSpos=0
        if predata:
            preprice=predata["preprice"]
            preBpos=predata["prebpos"]
            preSpos=predata["prespos"]
        prereturn=self.returnsobj.getpredata(timekey)
        price=t["LastPrice"]
        if not prereturn:
            prenet=1
            preplbp=0
            prebenchmark_net = 1
        else:
            prenet=prereturn["net"]
            preplbp=prereturn["plbp"]
            prebenchmark_net=prereturn["benchmark_net"]
        todayplbp=0
        todaynet=1
        todayreturn=0
        benchmark=0
        benchmark_net=1
        for i in self.bstoday:
            if i["bs"]=="buy":
                todayplbp=todayplbp+price-i["price"]
            elif i["bs"]=="sell":
                todayplbp=todayplbp-price+i["price"]
        if preprice:
            todayplbp = (price - preprice) * (preBpos - preSpos) + todayplbp
            todayreturn=todayplbp/preprice
            todaynet=todaynet+todayreturn
            benchmark=price/preprice-1
            benchmark_net=prebenchmark_net*(1+benchmark)
        else:
            todayreturn=todayplbp/price
            todaynet=todaynet+todayreturn
            benchmark=0
            benchmark_net=1
        plbp = todayplbp + preplbp
        net=todaynet*prenet
        self.returnsobj.updatedata(timekey, {"net":net,"plbp":plbp,"todayplbp":todayplbp,"return":todayreturn,"benchmark":benchmark,"benchmark_net":benchmark_net})
        pred={"preprice":price,"prespos":0,"prebpos":0}
        for i in self.sellorders:
            pred["prespos"]=pred["prespos"]+i["qty"]
        for i in self.buyorders:
            pred["prebpos"]=pred["prebpos"]+i["qty"]
        self.preprice.updatedata(timekey,pred)
        self.bstoday.reset()
    def summary(self):
        import pandas as pd
        rst = {}
        if self.orders:
            o=pd.DataFrame(self.orders)
            rst["总收益点数_逐笔"]=o["pl"].sum()
            rst["交易来回数_逐笔"]=len(o)
            rst["均收益_逐笔"] = rst["总收益点数_逐笔"]/rst["交易来回数_逐笔"]
            rst["0笔数_逐笔"]=len(o[o["pl"]==0])
            rst["赚钱笔数_逐笔"]=len(o[o["pl"]>0])
            rst["亏钱笔数_逐笔"] = len(o[o["pl"] < 0])
            rst["胜率_逐笔"]=rst["赚钱笔数_逐笔"]/rst["亏钱笔数_逐笔"]
            rst["盈亏比_逐笔"]=(o[o["pl"] > 0]["pl"].sum())/abs(o[o["pl"]<0]["pl"].sum())
            import pandas as pd
            import pyfinance as pf
            if self.returns:
                r = pd.DataFrame(self.returns)
                r.index = r["timekey"]
                rr = pf.TSeries(r["return"])
                rr.freq = "B"
                benchmark_rets = pf.TSeries(r["benchmark"])
                rst["年化收益_逐日"]=rr.anlzd_ret()
                rst["累计收益_逐日"]=rr.cuml_ret()
                rst["年化标准差_逐日"]=rr.anlzd_stdev()
                rst["上行期占比_逐日"] = rr.pct_positive()
                rst["下行期占比_逐日"] = rr.pct_negative()
                rst["下行标准差_逐日"]=rr.semi_stdev()
                rst["上行比下行期_逐日"]=rst["上行期占比_逐日"]/rst["下行期占比_逐日"]
                rst["最大回撤_逐日"]=rr.max_drawdown()
                rst["最大回撤天数_逐日"]=rr.drawdown_recov().days
                rst["收益最大回撤比_逐日"]=rr.calmar_ratio()
                rst["跑赢基准占比_逐日"]=rr.batting_avg(benchmark_rets)
                rst["夏普比率_逐日"]=rr.sharpe_ratio()
                r["drawdown"]=rr.drawdown_idx()
                self.returns_df=r
                self.returns=r.to_dict("records")
                self.rr=rr
            self.summarydata=rst
        return self.summarydata
    def summry_echarts(self):
        if not self.summarydata:
            self.summary()

        from jili.report.return_chart import return_chart
        chart=return_chart()
        if self.summarydata:
            chart.add_net(self.returns_df["net"])
            chart.add_net(self.returns_df["benchmark_net"],name="基准")
            chart.add_sub_Bar(self.returns_df["drawdown"],name="回撤",field=None)
            chart.add_sub_Bar(self.returns_df["todayplbp"], name="日盈亏", field=None)
            chart.add_sub_Bar_nozoom(self.rr.rollup(freq="W"))
            chart.add_sub_Bar_nozoom(self.rr.rollup(freq="M"))
            chart.add_sub_Bar_nozoom(self.rr.rollup(freq="Q"))
        return chart

    def save(self, name="pos"):
        from jili.core import save
        import os
        if "obj" in self.ssconfig.keys():
            name0=self.ssconfig["obj"]+"_"+name
        else:
            name0=name
        # baseurl=os.path.realpath(__file__)
        base_url = os.path.abspath(os.path.dirname(
            os.path.realpath(__file__)) + os.path.sep + "../../deps/qlyserver/data" + os.path.sep + name)
        save(self, base_url)
    def summary_pyfolio(self):
        import pyfolio as pf
        import pandas as pd
        import matplotlib.pyplot as plt
        returnsdata=pd.DataFrame(self.returns)
        returnsdata.index=returnsdata["timekey"]
        returns=returnsdata["return"]
        benchmark_rets=returnsdata["benchmark"]
        returns = returns.tz_localize('UTC')
        benchmark_rets = benchmark_rets.tz_localize('UTC')
        live_start_date = self.orders[0]["timekey"]
        live_start_date=live_start_date.strftime("%Y-%m-%d")
        pf.create_returns_tear_sheet(returns, benchmark_rets=benchmark_rets)
        plt.show()



class pos_reserch_fixfund:
    def __init__(self, reserver=False):
        """
        单品种交易研究；支持净值曲线
        支持多层次开仓，多次平仓；先开先平
        支持多空同时持仓
        buy 买持仓单
        sell 买持仓单
        orders 完成一笔买卖订单
        stat：持仓状态
        逐笔结算方式
        """
        self.buyorders = []
        self.sellorders = []
        self.orders = []
        self.stat = "null"  #
        self.reserver = reserver
        self.nets = {}

    def buy(self, price, qty, timekey):
        if self.reserver:
            self.__sell(price, qty, timekey)
        else:
            self.__buy(price, qty, timekey)

    def sell(self, price, qty, timekey):
        if not self.reserver:
            self.__sell(price, qty, timekey)
        else:
            self.__buy(price, qty, timekey)

    def sellopen(self, price, qty, timekey):
        if not self.reserver:
            self.__sellopen(price, qty, timekey)
        else:
            self.__buyopen(price, qty, timekey)

    def buyopen(self, price, qty, timekey):
        if self.reserver:
            self.__sellopen(price, qty, timekey)
        else:
            self.__buyopen(price, qty, timekey)

    def buyclose(self, price, qty, timekey):
        if self.reserver:
            self.__sellclose(price, qty, timekey)
        else:
            self.__buyclose(price, qty, timekey)

    def sellclose(self, price, qty, timekey):
        if not self.reserver:
            self.__sellclose(price, qty, timekey)
        else:
            self.__buyclose(price, qty, timekey)

    def closelong(self, price, timekey):
        if self.reserver:
            self.__closeshort(price, timekey)
        else:
            self.__closelong(price, timekey)

    def closeshort(self, price, timekey):
        if not self.reserver:
            self.__closeshort(price, timekey)
        else:
            self.__closelong(price, timekey)

    def __buy(self, price, qty, timekey):
        if self.sellorders:
            for i in self.sellorders:
                i["buyprice"] = price
                i["buytimekey"] = timekey
                i["pl"] = (i["sellprice"] - i["buyprice"] - 1) * i["qty"]
                self.orders.append(i)
        pos = {"buyprice": price, "buytimekey": timekey, "qty": qty}
        self.buyorders.append(pos)
        self.stat = "long"

    def __sell(self, price, qty, timekey):
        if self.buyorders:
            for i in self.buyorders:
                i["sellprice"] = price
                i["selltimekey"] = timekey
                i["pl"] = (i["sellprice"] - i["buyprice"] - 1) * i["qty"]
                self.orders.append(i)
        pos = {"sellprice": price, "selltimekey": timekey, "qty": qty}
        self.sellorders.append(pos)
        self.stat = "short"

    def __buyopen(self, price, qty, timekey):
        pos = {"buyprice": price, "buytimekey": timekey, "qty": qty}
        self.buyorders.append(pos)
        if self.sellorders:
            self.stat = "all"
        else:
            self.stat = "long"

    def __sellopen(self, price, qty, timekey):
        pos = {"sellprice": price, "selltimekey": timekey, "qty": qty}
        self.sellorders.append(pos)
        if self.buyorders:
            self.stat = "all"
        else:
            self.stat = "short"

    def __buyclose(self, price, qty, timekey):
        if self.sellorders:
            qty0 = qty
            while qty0 > 0:
                order = self.sellorders[0]
                if order["qty"] > qty:
                    order["qty"] = order["qty"] - qty
                    order0 = copy.deepcopy(order)
                    order0["qty"] = qty
                    order0["buyprice"] = price
                    order0["buytimekey"] = timekey
                    order0["pl"] = (order0["sellprice"] - order0["buyprice"] - 1) * order0["qty"]
                    self.orders.append(order0)
                else:
                    order0 = self.sellorders.pop(0)
                    order0["qty"] = qty
                    order0["buyprice"] = price
                    order0["buytimekey"] = timekey
                    order0["pl"] = (order0["sellprice"] - order0["buyprice"] - 1) * order0["qty"]
                    self.orders.append(order0)
                qty0 = qty - order["qty"]
        self.checkstat()

    def __sellclose(self, price, qty, timekey):
        if self.buyorders:
            qty0 = qty
            while qty0 > 0:
                order = self.buyorders[0]
                if order["qty"] > qty:
                    order["qty"] = order["qty"] - qty
                    order0 = copy.deepcopy(order)
                    order0["qty"] = qty
                    order0["sellprice"] = price
                    order0["selltimekey"] = timekey
                    order0["pl"] = (order0["sellprice"] - order0["buyprice"] - 1) * order0["qty"]
                    self.orders.append(order0)
                else:
                    order0 = self.buyorders.pop(0)
                    order0["qty"] = qty
                    order0["sellprice"] = price
                    order0["selltimekey"] = timekey
                    order0["pl"] = (order0["sellprice"] - order0["buyprice"] - 1) * order0["qty"]
                    self.orders.append(order0)
                qty0 = qty - order["qty"]
        self.checkstat()

    def __closelong(self, price, timekey):
        if self.buyorders:
            for i in self.buyorders:
                i["sellprice"] = price
                i["selltimekey"] = timekey
                i["pl"] = (i["sellprice"] - i["buyprice"] - 1) * i["qty"]
                self.orders.append(i)
        if self.sellorders:
            self.stat = "short"
        else:
            self.stat = "null"

    def __closeshort(self, price, timekey):
        if self.sellorders:
            for i in self.sellorders:
                i["buyprice"] = price
                i["buytimekey"] = timekey
                i["pl"] = (i["sellprice"] - i["buyprice"] - 1) * i["qty"]
                self.orders.append(i)
        if self.buyorders:
            self.stat = "long"
        else:
            self.stat = "null"

    def checkstat(self):
        if self.sellorders:
            if self.buyorders:
                self.stat = "all"
            else:
                self.stat = "short"
        else:
            if self.buyorders:
                self.stat = "long"
            else:
                self.stat = "null"

    def on1dbar(self, bar):
        tk = bar["timekey"]
        timekey = datetime.datetime(year=tk.year, month=tk.month, day=tk.day)
        """
        if self.preprice:

        else:
            if self.orders:

        self.preprice = bar["close"]
        self.nets
        """
    def summary(self):
        import pandas as pd
        rst = {}
        if self.orders:
            o = pd.DataFrame(self.orders)

            rst["pl_total"] = o["pl"].sum()
            rst["tarde_num"] = len(o)
            rst["pl_0"] = len(o[o["pl"] == 0])
            rst["pl_+0"] = len(o[o["pl"] > 0])
            rst["pl_-0"] = len(o[o["pl"] < 0])
        return rst